package net.tksl.crm.dao.impl;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import net.tksl.crm.dao.DatabaseObjectDao;
import net.tksl.crm.util.LoggerUtil;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

@Repository("databaseObjectDaoImpl")
public class DatabaseObjectDaoImpl implements DatabaseObjectDao {

	static Logger logger = Logger.getLogger(DatabaseObjectDaoImpl.class);

	@Autowired
	@Qualifier("sessionFactory")
	private SessionFactory sessionFactory;
	
	public Integer obtenerTotalRegistros(Class<?> claseDeMapeo){
		Session sesion = sessionFactory.getCurrentSession();

		Criteria criteria = sesion.createCriteria(claseDeMapeo);
		criteria = criteria.setProjection(Projections.rowCount());

		Integer count = (Integer) criteria.uniqueResult();

		if(count == null){
			count = 0;
		}
		
		return count;
	}

	public List<?> listarRegistrosPaginados(Class<?> claseDeMapeo,Map<String,Object> parametros){
		Session sesion = sessionFactory.getCurrentSession();
		
		Integer pagina = (Integer)parametros.get("pagina");
		Integer numFilas = (Integer)parametros.get("numFilas");
		Integer totalPaginas = (Integer)parametros.get("totalPaginas");
		String campoOrden = (String)parametros.get("campoOrden");
		String tipoOrden = (String)parametros.get("tipoOrden");
		
		if(pagina > totalPaginas){
			pagina = totalPaginas;
		}
		
		Integer paginaInicio = numFilas * pagina - numFilas;
		
		String hql = "from "+claseDeMapeo.getSimpleName()+" order by "+campoOrden+" "+tipoOrden;
		
		Query query = sesion.createQuery(hql);
		query.setFirstResult(paginaInicio);
		query.setMaxResults(numFilas);
		
		List<?> listaRegistros = (List<?>)query.list();
		
		return listaRegistros;
	}
	
	public String persist(Object entity) {
		String mensaje = "";
		try{
			Session sesion = sessionFactory.getCurrentSession();
			sesion.save(entity);
		}catch(Exception e){
			mensaje = e.getLocalizedMessage();
			LoggerUtil.error(logger,mensaje);
		}
		return mensaje;
	}

	public void persist(Object[] entities) {
		for(int i = 0; i < entities.length; i++) {  
	        persist(entities[i]);  
	    }
	}

	public void persist(List<?> entities) {
		if(entities!=null){
			int limite = entities.size();
			for(int i=0;i<limite;i++){
				persist(entities.get(i));
			}	
		}
	}
		
	@SuppressWarnings("unchecked")
	public <T> T findById(Class<T> entityClass,int id) {
		Session sesion = sessionFactory.getCurrentSession();
		T entity = (T)sesion.get(entityClass,id);
		return entity;
	}

	@SuppressWarnings("unchecked")
	public <T> T load(Class<T> entityClass, Serializable id) {
		Session sesion = sessionFactory.getCurrentSession();
	    T entity = (T)sesion.load(entityClass, id);  
        return entity;  
	}

	@SuppressWarnings("unchecked")	
	public <T> List<T> findByHql(String hql) {
		 Session sesion = sessionFactory.getCurrentSession();
		 Query query = sesion.createQuery(hql);
		 List<T> entities = (List<T>)query.list();
	     return entities;  
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> findByHqlOrderBy(Class<T> entityClass, String campo,String tipoOrden) {
		String hql = "from "+entityClass.getSimpleName()+" e order by e."+campo+" "+tipoOrden;
		Session sesion = sessionFactory.getCurrentSession();
		Query query = sesion.createQuery(hql);
		List<T> entities = (List<T>)query.list();
		return entities;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> findByProperty(Class<T> entityClass,String property, Object value) {
		String hql = "from "+entityClass.getSimpleName()+ " e where e."+ property + "="+value;
		Session sesion = sessionFactory.getCurrentSession();
		Query query = sesion.createQuery(hql);
		List<T> entities = (List<T>)query.list(); 
		return entities;
	}

	public void delete(Object obj) {
		Session sesion = sessionFactory.getCurrentSession();
		sesion.delete(obj);
	}
}